package com.sumer.psychology.common.test;

import com.sumer.psychology.common.domain.model.DomainEvent;
import com.sumer.psychology.common.domain.model.DomainEventPublisher;
import com.sumer.psychology.common.domain.model.DomainEventSubscriber;
import org.junit.Before;

import java.util.ArrayList;
import java.util.List;

/**
 * 测试事件
 * <p/>
 * User: zhenguang.zhu
 * Date: 2014/8/22
 * Time: 13:46
 */
public abstract class EventTrackingTestCase {
    private List<Class<? extends DomainEvent>> handledEvents;

    protected EventTrackingTestCase() {
        super();
    }

    protected void expectedEvent(Class<? extends DomainEvent> aDomainEventType) {
        this.expectedEvent(aDomainEventType, 1);
    }

    protected void expectedEvent(Class<? extends DomainEvent> aDomainEventType, int aTotal) {
        int count = 0;

        for (Class<? extends DomainEvent> type : this.handledEvents) {
            if (type == aDomainEventType) {
                ++count;
            }
        }

        if (count != aTotal) {
            throw new IllegalStateException("Expected " + aTotal + " " + aDomainEventType.getSimpleName() + " events, but handled "
                    + this.handledEvents.size() + " events: " + this.handledEvents);
        }
    }

    protected void expectedEvents(int anEventCount) {
        if (this.handledEvents.size() != anEventCount) {
            throw new IllegalStateException("Expected " + anEventCount + " events, but handled " + this.handledEvents.size()
                    + " events: " + this.handledEvents);
        }
    }

    @Before
    public void setUp() {
        DomainEventPublisher.instance().reset();

        DomainEventPublisher.instance().subscribe(new DomainEventSubscriber<DomainEvent>() {
            @Override
            public void handleEvent(DomainEvent aDomainEvent) {
                handledEvents.add(aDomainEvent.getClass());
            }

            @Override
            public Class<DomainEvent> subscribedToEventType() {
                return DomainEvent.class;
            }
        });

        this.handledEvents = new ArrayList<Class<? extends DomainEvent>>();
    }
}
